package com.quanquan.parking.utils;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Map;

/**
 * 请求发送方式
 * 
 * @author Administrator
 *
 */
public class Request {

	private static Logger logger = LoggerFactory.getLogger(Request.class);

	/**
	 * post json 方式发送请求
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static String postJson(String url, Object params) {
		Long s = System.currentTimeMillis();
		String jsonStr = JSON.toJSONString(params);
		InputStream instr = null;
		try {
			byte[] jsonData = jsonStr.getBytes("UTF-8");
			URL netUrl = new URL(url);
			URLConnection urlCon = netUrl.openConnection();
			urlCon.setDoOutput(true);
			urlCon.setDoInput(true);
			urlCon.setUseCaches(false);
			urlCon.setRequestProperty("Content-Type", "application/json");
			urlCon.setRequestProperty("Content-length", String.valueOf(jsonData.length));
			DataOutputStream printout = new DataOutputStream(urlCon.getOutputStream());
			printout.write(jsonData);
			printout.flush();
			printout.close();
			instr = urlCon.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(instr, "UTF-8"));
			StringBuffer out = new StringBuffer();
			String line;
			while (null != (line = br.readLine())) {
				out.append(line);
			}
			return out.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		} finally {
			try {
				instr.close();
			} catch (Exception ex) {
				return "";
			}
		}
	}
	
	
	public static String postXml(String url, String xml,String passwd,InputStream certStream) {
		InputStream instr = null;
		try {
			// 证书
	        char[] password = passwd.toCharArray();
	        KeyStore ks = KeyStore.getInstance("PKCS12");
	        ks.load(certStream, password);

	        // 实例化密钥库 & 初始化密钥工厂
	        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
	        kmf.init(ks, password);

	        // 创建 SSLContext
	        SSLContext sslContext = SSLContext.getInstance("TLS");
	        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
	        
			byte[] jsonData = xml.getBytes("UTF-8");
			URL netUrl = new URL(url);
			HttpsURLConnection urlCon = (HttpsURLConnection) netUrl.openConnection();
			urlCon.setDoOutput(true);
			urlCon.setDoInput(true);
			urlCon.setUseCaches(false);
			urlCon.setSSLSocketFactory(sslContext.getSocketFactory());
			urlCon.setRequestProperty("Content-Type", "text/xml");
			urlCon.setRequestProperty("Content-length", String.valueOf(jsonData.length));
			DataOutputStream printout = new DataOutputStream(urlCon.getOutputStream());
			printout.write(jsonData);
			printout.flush();
			printout.close();
			instr = urlCon.getInputStream();
			StringBuffer out = new StringBuffer();
			byte[] bis = new byte[4096];
			int n = 0;
			while ((n = instr.read(bis)) != -1) {
				out.append(new String(bis, 0, n, "UTF-8"));
			}
			return out.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		} finally {
			try {
				instr.close();
			} catch (Exception ex) {
				return "";
			}
		}
	}
	public static String postXml(String url, String xml){
		return postXml(url, xml, null);
	}
	public static String postXml(String url, String xml,Map<String,String> headerInfo) {
		Long s = System.currentTimeMillis();
		logger.info("postXml 请求地址:{} 请求参数：{}", url, xml);
		InputStream instr = null;
		try {
			byte[] jsonData = xml.getBytes("UTF-8");
			URL netUrl = new URL(url);
			URLConnection urlCon = netUrl.openConnection();
			urlCon.setDoOutput(true);
			urlCon.setDoInput(true);
			urlCon.setUseCaches(false);
			urlCon.setRequestProperty("Content-Type", "text/xml");
			if(headerInfo!=null&&headerInfo.size()>0){
				for (String key:headerInfo.keySet()) {
					urlCon.setRequestProperty(key, headerInfo.get(key));
				}
			}
			urlCon.setRequestProperty("Content-length", String.valueOf(jsonData.length));
			DataOutputStream printout = new DataOutputStream(urlCon.getOutputStream());
			printout.write(jsonData);
			printout.flush();
			printout.close();
			instr = urlCon.getInputStream();
			StringBuffer out = new StringBuffer();
			byte[] bis = new byte[4096];
			int n = 0;
			while ((n = instr.read(bis)) != -1) {
				out.append(new String(bis, 0, n, "UTF-8"));
			}
			logger.info("postXml 请求返回值={}", out);
			logger.info("postXml 请求用时={}", System.currentTimeMillis() - s);
			
			return out.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		} finally {
			try {
				instr.close();
			} catch (Exception ex) {
				return "";
			}
		}
	}

	public static String sendGet(String url, Map<String, Object> params) {
		return sendGet(url, params,true);
	}
	public static String sendGet(String url, Map<String, Object> params,boolean flag) {
		StringBuffer result = new StringBuffer();
		BufferedReader in = null;

		StringBuffer urlNameString = new StringBuffer().append(url).append("?");
		if (params != null) {
			for (String key : params.keySet()) {
				try {
					urlNameString.append(key).append("=").append(URLEncoder.encode((String) params.get(key), "UTF-8")).append("&");
				}catch (Exception e ){
					e.printStackTrace();
				}
			}
			url = urlNameString.substring(0, urlNameString.lastIndexOf("&"));
		}

		if(flag)
		logger.info("sendGet 请求地址:{}", url);

		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置超时时间
			connection.setConnectTimeout(5000);
			connection.setReadTimeout(15000);
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("Accept-Charset", "UTF-8");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result.append(line);
			}
			if (in != null) {
				in.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(flag)
		logger.info("sendGet 返回值:{}", result.toString());
		return result.toString();
	}

	
	public static String sendPost(String url, Map<String, Object> params) {
		return sendPost(url, params,true);
	}
	
	public static String sendPost(String url, Map<String, Object> params,boolean flag) {
		StringBuffer result = new StringBuffer();
		StringBuffer paramString = new StringBuffer();
		if (params != null) {
			for (String key : params.keySet()) {
				paramString.append(key).append("=").append(params.get(key)).append("&");
			}
		}
		if(flag)
			logger.info("sendPost 请求地址:{} 请求参数:{}", url,paramString.toString());
		try {
			PrintWriter out = null;
			BufferedReader in = null;
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置超时时间
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(15000);
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("Accept-Charset", "UTF-8");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			if(paramString.lastIndexOf("&")>0) {
				out.print(paramString.substring(0, paramString.lastIndexOf("&")));
			}else{
				out.print(paramString);
			}
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result.append(line);
			}
			if (out != null) {
				out.close();
			}
			if (in != null) {
				in.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(flag)
			logger.info("sendPost 返回值:{}", result.toString());
		return result.toString();
	}

	public static String fileUpload(String urlStr, Map<String, String> params, String fileParamName,InputStream inputStream,
			String filename) {
		String res = "";
		HttpURLConnection conn = null;
		// boundary就是request头和上传文件内容的分隔符
		String BOUNDARY = "---------------------------123821742118716";
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(30000);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
			conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
			OutputStream out = new DataOutputStream(conn.getOutputStream());
			// text
			if (params != null) {
				StringBuffer strBuf = new StringBuffer();
				for (String key : params.keySet()) {
					String value = params.get(key);
					if (StringUtils.isEmpty(value)) {
						continue;
					}
					strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
					strBuf.append("Content-Disposition: form-data; name=\"").append(key).append("\"\r\n\r\n");
					strBuf.append(value);
				}
				logger.info("fileUpload 请求地址:{} 请求参数:{}", urlStr,strBuf.toString());
				out.write(strBuf.toString().getBytes());
			}
			// file
			if (inputStream != null) {
				String contentType = "application/octet-stream";
				if (filename.endsWith(".png")) {
					contentType = "image/png";
				} else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".jpe")) {
					contentType = "image/jpeg";
				} else if (filename.endsWith(".gif")) {
					contentType = "image/gif";
				} else if (filename.endsWith(".ico")) {
					contentType = "image/image/x-icon";
				}
				
				StringBuffer strBuf = new StringBuffer();
				strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
				strBuf.append(
						"Content-Disposition: form-data; name=\"" + fileParamName + "\"; filename=\"" + filename + "\"\r\n");
				strBuf.append("Content-Type:" + contentType + "\r\n\r\n");
				out.write(strBuf.toString().getBytes());
				int bytes = 0;
				byte[] bufferOut = new byte[1024];
				while ((bytes = inputStream.read(bufferOut)) != -1) {
					out.write(bufferOut, 0, bytes);
				}
				inputStream.close();
			}
			byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
			out.write(endData);
			out.flush();
			out.close();
			// 读取返回数据
			StringBuffer strBuf = new StringBuffer();
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				strBuf.append(line).append("\n");
			}
			res = strBuf.toString();
			reader.close();
			reader = null;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		logger.info("fileUpload 返回值:{}", res);
		return res;
	}
	public static String fileUpload(String urlStr, Map<String, String> params, String fileParamName,File file) {
		String res = "";
		HttpURLConnection conn = null;
		// boundary就是request头和上传文件内容的分隔符
		String BOUNDARY = "---------------------------123821742118716";
		logger.info("fileUpload 请求地址:{} 请求参数:{}", urlStr,fileParamName+":"+file.getName());
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(30000);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
			conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
			OutputStream out = new DataOutputStream(conn.getOutputStream());
			// text
			if (params != null) {
				StringBuffer strBuf = new StringBuffer();
				for (String key : params.keySet()) {
					String value = params.get(key);
					if (StringUtils.isEmpty(value)) {
						continue;
					}
					strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
					strBuf.append("Content-Disposition: form-data; name=\"").append(key).append("\"\r\n\r\n");
					strBuf.append(value);
				}
				logger.info("fileUpload 请求地址:{} 请求参数:{}", urlStr,strBuf.toString());
				out.write(strBuf.toString().getBytes());
			}
			if (file != null) {
				String filename=file.getName();
				String contentType = "application/octet-stream";
				if (filename.endsWith(".png")) {
					contentType = "image/png";
				} else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".jpe")) {
					contentType = "image/jpeg";
				} else if (filename.endsWith(".gif")) {
					contentType = "image/gif";
				} else if (filename.endsWith(".ico")) {
					contentType = "image/image/x-icon";
				}
				
				StringBuffer strBuf = new StringBuffer();
				strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
				strBuf.append(
						"Content-Disposition: form-data; name=\"" + fileParamName + "\"; filename=\"" + filename + "\"\r\n");
				strBuf.append("Content-Type:" + contentType + "\r\n\r\n");
				out.write(strBuf.toString().getBytes());
				int bytes = 0;
				byte[] bufferOut = new byte[1024];
				DataInputStream inputStream = new DataInputStream(  
                        new FileInputStream(file));  
				
				while ((bytes = inputStream.read(bufferOut)) != -1) {
					out.write(bufferOut, 0, bytes);
				}
				inputStream.close();
			}
			byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
			out.write(endData);
			out.flush();
			out.close();
			// 读取返回数据
			StringBuffer strBuf = new StringBuffer();
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = null;
			while ((line = reader.readLine()) != null) {
				strBuf.append(line).append("\n");
			}
			res = strBuf.toString();
			reader.close();
			reader = null;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		logger.info("fileUpload 返回值:{}", res);
		return res;
	}

}
